package org.sardine.beans;

import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;

/**
 * @author BearBear
 * 
 * 根据Type提供的类型信息，将字符串转换为对应的基本类型、包装类型，基本类型数组，包装类型数组
 *
 */
public abstract class StringValueConverter {
	
	private static final Logger log = Logger.getLogger(StringValueConverter.class);
	
	private static final List<String> primitiveTypeNameList = new ArrayList<String>();
	private static final List<String> wrapperTypeNameList = new ArrayList<String>();
	private static final List<String> primitiveArrayTypeNameList = new ArrayList<String>();
	private static final List<String> wrapperArrayTypeNameList = new ArrayList<String>();
	
	private static final String PRIMITIVE_BOOLEAN = "boolean";
	private static final String PRIMITIVE_BYTE = "byte";
	private static final String PRIMITIVE_CHAR = "char";
	private static final String PRIMITIVE_DOUBLE = "double";
	private static final String PRIMITIVE_FLOAT = "float";
	private static final String PRIMITIVE_INT = "int";
	private static final String PRIMITIVE_LONG = "long";
	private static final String PRIMITIVE_SHORT = "short";
	
	private static final String WRAPPER_BOOLEAN = "java.lang.Boolean";
	private static final String WRAPPER_BYTE = "java.lang.Byte";
	private static final String WRAPPER_CHARACTER = "java.lang.Character";
	private static final String WRAPPER_DOUBLE = "java.lang.Double";
	private static final String WRAPPER_FLOAT = "java.lang.Float";
	private static final String WRAPPER_INTEGER = "java.lang.Integer";
	private static final String WRAPPER_LONG = "java.lang.Long";
	private static final String WRAPPER_SHORT = "java.lang.Short";
	
	private static final String SPLIT_TOKENS = ",| ";
	
	private static final String ARRAY_PRIMITIVE_BOOLEAN = "boolean[]";
	private static final String ARRAY_PRIMITIVE_BYTE = "byte[]";
	private static final String ARRAY_PRIMITIVE_CHAR = "char[]";
	private static final String ARRAY_PRIMITIVE_DOUBLE = "double[]";
	private static final String ARRAY_PRIMITIVE_FLOAT = "float[]";
	private static final String ARRAY_PRIMITIVE_INT = "int[]";
	private static final String ARRAY_PRIMITIVE_LONG = "long[]";
	private static final String ARRAY_PRIMITIVE_SHORT = "short[]";
	private static final String ARRAY_WRAPPER_BOOLEAN = "java.lang.Boolean[]";
	private static final String ARRAY_WRAPPER_BYTE = "java.lang.Byte[]";
	private static final String ARRAY_WRAPPER_CHARACTER = "java.lang.Character[]";
	private static final String ARRAY_WRAPPER_DOUBLE = "java.lang.Double[]";
	private static final String ARRAY_WRAPPER_FLOAT = "java.lang.Float[]";
	private static final String ARRAY_WRAPPER_INTEGER = "java.lang.Integer[]";
	private static final String ARRAY_WRAPPER_LONG = "java.lang.Long[]";
	private static final String ARRAY_WRAPPER_SHORT = "java.lang.Short[]";
	private static final String ARRAY_WRAPPER_STRING = "java.lang.String[]";
	
	//private final Map<String,Converter> typeNameConverter;
	
	static{
		/*
		this.typeNameConverter = new HashMap<String,Converter>();
		this.typeNameConverter.put("boolean",new Converter(){});
		this.typeNameConverter.put("byte",new Converter(){});
		this.typeNameConverter.put("char",new Converter(){});
		this.typeNameConverter.put("double",new Converter(){});
		this.typeNameConverter.put("float",new Converter(){});
		this.typeNameConverter.put("int",new Converter(){});
		this.typeNameConverter.put("long",new Converter(){});
		this.typeNameConverter.put("short",new Converter(){});*/
		
		String[] primitiveTypeNames = new String[]{
					PRIMITIVE_BOOLEAN,
					PRIMITIVE_BYTE,
					PRIMITIVE_CHAR,
					PRIMITIVE_DOUBLE,
					PRIMITIVE_FLOAT,
					PRIMITIVE_INT,
					PRIMITIVE_LONG,
					PRIMITIVE_SHORT};
		
		String[] wrapperTypeNames = new String[]{
					WRAPPER_BOOLEAN,
					WRAPPER_BYTE,
					WRAPPER_CHARACTER,
					WRAPPER_DOUBLE,
					WRAPPER_FLOAT,
					WRAPPER_INTEGER,
					WRAPPER_LONG,
					WRAPPER_SHORT};
		
		String[] primitiveArrayTypeNames = new String[]{
					ARRAY_PRIMITIVE_BOOLEAN,
					ARRAY_PRIMITIVE_BYTE,
					ARRAY_PRIMITIVE_CHAR,
					ARRAY_PRIMITIVE_DOUBLE,
					ARRAY_PRIMITIVE_FLOAT,
					ARRAY_PRIMITIVE_INT,
					ARRAY_PRIMITIVE_LONG,
					ARRAY_PRIMITIVE_SHORT};
		
		String[] wrapperArrayTypeNames = new String[]{
					ARRAY_WRAPPER_BOOLEAN,
					ARRAY_WRAPPER_BYTE,
					ARRAY_WRAPPER_CHARACTER,
					ARRAY_WRAPPER_DOUBLE,
					ARRAY_WRAPPER_FLOAT,
					ARRAY_WRAPPER_INTEGER,
					ARRAY_WRAPPER_LONG,
					ARRAY_WRAPPER_SHORT,
					ARRAY_WRAPPER_STRING};
		
		
		primitiveTypeNameList.addAll(Arrays.asList(primitiveTypeNames));
		wrapperTypeNameList.addAll(Arrays.asList(wrapperTypeNames));
		primitiveArrayTypeNameList.addAll(Arrays.asList(primitiveArrayTypeNames));
		wrapperArrayTypeNameList.addAll(Arrays.asList(wrapperArrayTypeNames));
		
	}
	
	public static Object convert(Type parameterType,String propertyValue){
		
		String typeName = parameterType.getTypeName();
		
		if(primitiveTypeNameList.contains(typeName)){
			return convert2PrimitiveOrWrapper(typeName,propertyValue);
			
		}else if(wrapperTypeNameList.contains(typeName)){
			return convert2PrimitiveOrWrapper(typeName,propertyValue);
			
		}else if(primitiveArrayTypeNameList.contains(typeName)){
			return convert2PrimitiveArray(typeName,propertyValue);
			
		}else if(wrapperArrayTypeNameList.contains(typeName)){
			return convert2WrapperArray(typeName,propertyValue);
			
		}else{
			return propertyValue;
		}
		
	}
	
	@Deprecated
	private Object convert2Primitive(String typeName,String propertyValue){
		
		if(PRIMITIVE_BOOLEAN.equals(typeName)){
			return "true".equalsIgnoreCase(propertyValue)?true:false;
		}else if(PRIMITIVE_BYTE.equals(typeName)){
			return Byte.parseByte(propertyValue);
		}else if(PRIMITIVE_CHAR.equals(typeName)){
			return propertyValue.charAt(0);
		}else if(PRIMITIVE_DOUBLE.equals(typeName)){
			return Double.parseDouble(propertyValue);
		}else if(PRIMITIVE_FLOAT.equals(typeName)){
			return Float.parseFloat(propertyValue);
		}else if(PRIMITIVE_INT.equals(typeName)){
			return Integer.parseInt(propertyValue);
		}else if(PRIMITIVE_LONG.equals(typeName)){
			return Long.parseLong(propertyValue);
		}else if(PRIMITIVE_SHORT.equals(typeName)){
			return Short.parseShort(propertyValue);
		}else{
			throw new StringValueConverterException("没有把 propertyValue 转换为 "+typeName+" 的处理方法");
		}
	}
	
	@Deprecated
	private Object convert2Wrapper(String typeName,String propertyValue){
		
		if(WRAPPER_BOOLEAN.equals(typeName)){
			return Boolean.valueOf(propertyValue);
		}else if(WRAPPER_BYTE.equals(typeName)){
			return Byte.valueOf(propertyValue);
		}else if(WRAPPER_CHARACTER.equals(typeName)){
			return Character.valueOf(propertyValue.charAt(0));
		}else if(WRAPPER_DOUBLE.equals(typeName)){
			return Double.valueOf(propertyValue);
		}else if(WRAPPER_FLOAT.equals(typeName)){
			return Float.valueOf(propertyValue);
		}else if(WRAPPER_INTEGER.equals(typeName)){
			return Integer.valueOf(propertyValue);
		}else if(WRAPPER_LONG.equals(typeName)){
			return Long.valueOf(propertyValue);
		}else if(WRAPPER_SHORT.equals(typeName)){
			return Short.valueOf(propertyValue);
		}else{
			throw new StringValueConverterException("没有把 propertyValue 转换为 "+typeName+" 的处理方法");
		}
		
	}
	
	private static Object convert2PrimitiveOrWrapper(String typeName,String propertyValue){
		
		log.debug("字符串值 "+propertyValue+" 开始转换为 "+typeName+" 类型");
		
		if(PRIMITIVE_BOOLEAN.equals(typeName)){
			return "true".equalsIgnoreCase(propertyValue)?true:false;
		}else if(PRIMITIVE_BYTE.equals(typeName)){
			return Byte.parseByte(propertyValue);
		}else if(PRIMITIVE_CHAR.equals(typeName)){
			return propertyValue.charAt(0);
		}else if(PRIMITIVE_DOUBLE.equals(typeName)){
			return Double.parseDouble(propertyValue);
		}else if(PRIMITIVE_FLOAT.equals(typeName)){
			return Float.parseFloat(propertyValue);
		}else if(PRIMITIVE_INT.equals(typeName)){
			return Integer.parseInt(propertyValue);
		}else if(PRIMITIVE_LONG.equals(typeName)){
			return Long.parseLong(propertyValue);
		}else if(PRIMITIVE_SHORT.equals(typeName)){
			return Short.parseShort(propertyValue);
		}else if(WRAPPER_BOOLEAN.equals(typeName)){
			return Boolean.valueOf(propertyValue);
		}else if(WRAPPER_BYTE.equals(typeName)){
			return Byte.valueOf(propertyValue);
		}else if(WRAPPER_CHARACTER.equals(typeName)){
			return Character.valueOf(propertyValue.charAt(0));
		}else if(WRAPPER_DOUBLE.equals(typeName)){
			return Double.valueOf(propertyValue);
		}else if(WRAPPER_FLOAT.equals(typeName)){
			return Float.valueOf(propertyValue);
		}else if(WRAPPER_INTEGER.equals(typeName)){
			return Integer.valueOf(propertyValue);
		}else if(WRAPPER_LONG.equals(typeName)){
			return Long.valueOf(propertyValue);
		}else if(WRAPPER_SHORT.equals(typeName)){
			return Short.valueOf(propertyValue);
		}else{
			throw new StringValueConverterException("没有把 propertyValue 转换为 "+typeName+" 的处理方法");
		}
	}
	
	private static Object arrayCopy(Object t,Object array,int length){
		
		log.debug("返回的数组类型是："+array.getClass().getName());
		System.arraycopy(t, 0, array, 0, length);
		return array;
		
	}
	
	private static Object convert2PrimitiveArray(String typeName,String propertyValue){
		
		Object arrayValue = null;
		String elmTypeName = typeName.substring(0,typeName.length()-2);
		String[] t = propertyValue.split(SPLIT_TOKENS);
		int arrayLength = t.length;
		
		log.debug("字符串值 "+propertyValue+" 开始转换为 "+elmTypeName+" 类型的数组,数组长度为："+arrayLength);
		
		if(ARRAY_PRIMITIVE_BOOLEAN.equals(typeName)){
			boolean[] values = new boolean[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Boolean) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_BYTE.equals(typeName)){
			byte[] values = new byte[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Byte) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_CHAR.equals(typeName)){
			char[] values = new char[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Character) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_DOUBLE.equals(typeName)){
			double[] values = new double[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Double) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_FLOAT.equals(typeName)){
			float[] values = new float[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Float) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_INT.equals(typeName)){
			int[] values = new int[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Integer) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_LONG.equals(typeName)){
			long[] values = new long[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Long) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else if(ARRAY_PRIMITIVE_SHORT.equals(typeName)){
			short[] values = new short[arrayLength];
			for(int i=0;i<arrayLength;i++){
				values[i] = (Short) convert2PrimitiveOrWrapper(elmTypeName,t[i]);
			}
			arrayValue = values;
			
		}else{
			throw new StringValueConverterException("没有把 propertyValue 转换为 "+typeName+" 的处理方法");
		}
		
		return arrayValue;
	
	}
	
	private static Object convert2WrapperArray(String typeName,String propertyValue){
		
		Object arrayValue = null;
		String elmTypeName = typeName.substring(0,typeName.length()-2);
		String[] t = propertyValue.split(SPLIT_TOKENS);
		int arrayLength = t.length;
		Object[] v = new Object[arrayLength];
		
		log.debug("字符串值 "+propertyValue+" 开始转换为 "+elmTypeName+" 类型的数组,数组长度为："+arrayLength);
		
		if(ARRAY_WRAPPER_STRING.equals(typeName)){
			return t;
		}
		
		for(int i=0;i<arrayLength;i++){
			v[i] = convert2PrimitiveOrWrapper(elmTypeName,t[i]);
		}
		
		if(ARRAY_WRAPPER_BOOLEAN.equals(typeName)){
			arrayValue = arrayCopy(v,new Boolean[arrayLength],arrayLength);
			
			
		}else if(ARRAY_WRAPPER_BYTE.equals(typeName)){
			arrayValue = arrayCopy(v,new Byte[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_CHARACTER.equals(typeName)){
			arrayValue = arrayCopy(v,new Character[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_DOUBLE.equals(typeName)){
			arrayValue = arrayCopy(v,new Double[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_FLOAT.equals(typeName)){
			arrayValue = arrayCopy(v,new Float[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_INTEGER.equals(typeName)){
			arrayValue = arrayCopy(v,new Integer[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_LONG.equals(typeName)){
			arrayValue = arrayCopy(v,new Long[arrayLength],arrayLength);
			
		}else if(ARRAY_WRAPPER_SHORT.equals(typeName)){
			arrayValue = arrayCopy(v,new Short[arrayLength],arrayLength);
			
		}else{
			throw new StringValueConverterException("没有把 propertyValue 转换为 "+typeName+" 的处理方法");
		}
		
		return arrayValue;
	
	}

}
